Veamos ahora el mismo ejemplo usando clases.
Para empezar, y como siempre, necesitaremos dos clases, una para nodo y otra para lista. Además la clase para nodo debe ser amiga de la clase lista, ya que ésta debe acceder a los miembros privados de nodo.
class nodo { public: nodo(int v, nodo *sig = NULL, nodo *ant = NULL) : valor(v), siguiente(sig), anterior(ant) {} private: int valor; nodo *siguiente; nodo *anterior; friend class lista; }; typedef nodo *pnodo; class lista { public: lista() : lista(NULL) {} ~lista(); void Insertar(int v); void Borrar(int v); bool ListaVacia() { return lista == NULL; } void Mostrar(); void Siguiente(); void Anterior(); void Primero(); void Ultimo(); pnodo Actual() { return lista; } int ValorActual() { return lista->valor; } private: pnodo lista; };
Ahora sólo necesitamos un puntero para referenciar la lista y movernos a través de ella. Hemos añadido funciones para avanzar y retroceder, moverse al primero o último nodo, obtener un puntero al nodo actual o su valor.
Los algoritmos para insertar y borrar elementos son los mismos que expusimos para el ejemplo C, tan sólo cambia el modo de crear y destruir nodos.
#include <iostream> using namespace std; #define ASCENDENTE 1 #define DESCENDENTE 0 class nodo { public: nodo(int v, nodo *sig = NULL, nodo *ant = NULL) : valor(v), siguiente(sig), anterior(ant) {} private: int valor; nodo *siguiente; nodo *anterior; friend class lista; }; typedef nodo *pnodo; class lista { public: lista() : plista(NULL) {} ~lista(); void Insertar(int v); void Borrar(int v); bool ListaVacia() { return plista == NULL; } void Mostrar(int); void Siguiente(); void Anterior(); void Primero(); void Ultimo(); bool Actual() { return plista != NULL; } int ValorActual() { return plista->valor; } private: pnodo plista; }; lista::~lista() { pnodo aux; Primero(); while(plista) { aux = plista; plista = plista->siguiente; delete aux; } } void lista::Insertar(int v) { pnodo nuevo; Primero(); // Si la lista está vacía if(ListaVacia() || plista->valor >v) { // Asignamos a lista un nuevo nodo de valor v y // cuyo siguiente elemento es la lista actual nuevo = new nodo(v, plista); if(!plista) plista = nuevo; else plista->anterior = nuevo; } else { // Buscar el nodo de valor menor a v // Avanzamos hasta el último elemento o hasta que el siguiente tenga // un valor mayor que v while(plista->siguiente &&plista->siguiente->valor <= v) Siguiente(); // Creamos un nuevo nodo después del nodo actual nuevo = new nodo(v, plista->siguiente, plista); plista->siguiente = nuevo; if(nuevo->siguiente) nuevo->siguiente->anterior = nuevo; } } void lista::Borrar(int v) { pnodo nodo; nodo = plista; while(nodo && nodo->valor < v) nodo = nodo->siguiente; while(nodo && nodo->valor > v) nodo = nodo->anterior; if(!nodo || nodo->valor != v) return; // Borrar el nodo if(nodo->anterior) // no es el primer elemento nodo->anterior->siguiente = nodo->siguiente; if(nodo->siguiente) // no el el último nodo nodo->siguiente->anterior = nodo->anterior; delete nodo; } void lista::Mostrar(int orden) { pnodo nodo; if(orden == ASCENDENTE) { Primero(); nodo = plista; while(nodo) { cout <<nodo->valor <<"-> "; nodo = nodo->siguiente; } } else { Ultimo(); nodo = plista; while(nodo) { cout << nodo->valor << "-> "; nodo = nodo->anterior; } } cout << endl; } void lista::Siguiente() { if(plista) plista = plista->siguiente; } void lista::Anterior() { if(plista) plista = plista->anterior; } void lista::Primero() { while(plista &&plista->anterior) plista = plista->anterior; } void lista::Ultimo() { while(plista && plista->siguiente) plista = plista->siguiente; } int main() { lista Lista; Lista.Insertar(20); Lista.Insertar(10); Lista.Insertar(40); Lista.Insertar(30); Lista.Mostrar(ASCENDENTE); Lista.Mostrar(DESCENDENTE); Lista.Primero(); cout << "Primero: " << Lista.ValorActual() << endl; Lista.Ultimo(); cout << "Ultimo: " << Lista.ValorActual() << endl; Lista.Borrar(10); Lista.Borrar(15); Lista.Borrar(45); Lista.Borrar(40); Lista.Mostrar(ASCENDENTE); Lista.Mostrar(DESCENDENTE); cin.get(); return 0; }
© Septiembre de 2001 Salvador Pozo, salvador@conclase.net